#include "PoolSystem.h"
#include "Camera.h"
#include "Physics.h"
#include "Player.h"
#include "Time.h"

#pragma region PoolSystem

std::map<std::string, float> PoolSystem::pools;

float* PoolSystem::AddToPool(std::string tag)
{
	return &(pools.emplace(tag, 0.0f).first->second);
}

#pragma endregion

#pragma region PoolTile

vector<PoolTile::SlidingObject> PoolTile::slidingObjects;
int PoolTile::iceCount = 0;
int PoolTile::iceCounter = 0;

PoolTile::PoolTile(string tag)
{
	this->objectID = "Water";
	this->tag = tag;
	this->poolHeat = PoolSystem::AddToPool(this->GetTag());
	this->isFrozen = false;
	this->SetCurTemp(*poolHeat);

	++iceCount;
	slideSpeed = 150.0f;
}

PoolTile::~PoolTile(void)
{
	--iceCount;
}

void PoolTile::Update(float deltaTime)
{
	this->SetCurTemp(*poolHeat);

	if(*poolHeat == this->MinTemp())
	{
		isFrozen = true;
		this->SetCanBeGrappled(true);
	}
	else
	{
		isFrozen = false;
		this->SetCanBeGrappled(false);
	}

	//////////////////////////////////////////////////
	// SLIDE OBJECTS ON THE ICE
	if(this->isFrozen == false)
		return;

	for(unsigned int i = 0; i < slidingObjects.size(); ++i)
	{
		if(slidingObjects[i].collided == 0)
		{
			if(slidingObjects[i].object->GetObjectID() == "Player")
			{
				Player* player = dynamic_cast<Player*>(slidingObjects[i].object);

				if(player != nullptr)
					player->ActivateMovement();
			}

			slidingObjects.erase(slidingObjects.begin() + i);

			--i;
			continue;
		}

		if(slidingObjects[i].wasMoved == true)
			continue;

		GameObject* obj = slidingObjects[i].object;

		if(slidingObjects[i].gotDelta && slidingObjects[i].current.fX == obj->GetPosX())
			obj->SetPosY(obj->GetPosY() - 8);
			//obj->SetPosX(slidingObjects[i].current.fX);

		tVector2D delta = slidingObjects[i].current - slidingObjects[i].previous;
		delta.fY = 0;

		if(slidingObjects[i].gotDelta == false && Vector2DLength(delta) > 1.0f)
		{
			delta = Vector2DNormalize(delta);
			slidingObjects[i].delta = delta.fX;
			slidingObjects[i].gotDelta = true;

			if(obj->GetObjectID() == "Player")
			{
				Player* player = dynamic_cast<Player*>(obj);

				if(player != nullptr)
					player->DeactivateMovement();
			}
		}
		else if(slidingObjects[i].gotDelta == true)
		{
			if(slidingObjects[i].previous.fX == slidingObjects[i].current.fX)
			{
				obj->SetPosY(obj->GetPosY() - 8);
			}
		}

		obj->SetPosX(obj->GetPosX() + slidingObjects[i].delta * slideSpeed * deltaTime);
		obj->SetHitBox(Physics::UpdateColRect(obj->GetHitBox(), (int)obj->GetPosX(), (int)obj->GetPosY()));

		slidingObjects[i].collided--;
		slidingObjects[i].wasMoved = true;

		slidingObjects[i].previous = slidingObjects[i].current;

		slidingObjects[i].current.fX = obj->GetPosX();
		slidingObjects[i].current.fY = obj->GetPosY();
	}

	++iceCounter;

	if(iceCounter == iceCount)
	{
		for(unsigned int i = 0; i < slidingObjects.size(); ++i)
			slidingObjects[i].wasMoved = false;
		iceCounter = 0;
	}
	//************************************************
}

void PoolTile::Render(void) const
{
	GameObject::Render();

	float alpha = 0.0f;
	
	if(alpha <= 0.0f)
		alpha = (-CurTemp() / (-MinTemp())) * 255.0f;

	RECT rect	= hitBox;
	rect.left	-= (long)Camera::GetInstance()->OffsetX();
	rect.right	-= (long)Camera::GetInstance()->OffsetX();
	rect.top	-= (long)Camera::GetInstance()->OffsetY();
	rect.bottom	-= (long)Camera::GetInstance()->OffsetY();

	CSGD_Direct3D::GetInstance()->DrawRect(rect, D3DCOLOR_ARGB((int)alpha, 255, 255, 255));
}

void PoolTile::HandleCollision(GameObject& other, CollisionInfo& info)
{
	if(isFrozen == false)
		return;

	if(info.Side == CollisionSide::BOTTOM)
		other.SetPosY(other.GetPosY() - (info.Overlap.bottom - info.Overlap.top));

	other.SetHitBox(Physics::UpdateColRect(other.GetHitBox(), (int)other.GetPosX(), (int)other.GetPosY()));

	bool add = true;
	unsigned int i = 0;
	for(; add && i < slidingObjects.size(); ++i)
		if(slidingObjects[i].object == &other)
			add = false;
	
	--i;

	if(add == true)
	{
		SlidingObject obj;
		obj.object = &other;
		obj.current.fX = obj.previous.fX = other.GetPosX();
		obj.current.fY = obj.previous.fY = other.GetPosY();
		obj.delta = 0.0f;
		obj.collided = 100;
		obj.gotDelta = false;

		slidingObjects.push_back(obj);
	}
	else if(i >= 0)
	{
		slidingObjects[i].collided = 100;
	}
}

void PoolTile::ResetToCheckPoint()
{

}

void PoolTile::SetCheckPointData()
{

}

void PoolTile::ApplyHeat(float amount)
{
	HeatPhysics::ApplyHeat(amount);

	*poolHeat = this->CurTemp();
}

#pragma endregion